/*
Day1 备注：验证“极简线性回归”在 2 维 toy 数据上能否只靠 STL 一步算出权重，
并给出合理预测。结论：可行；为后续对话模型提供底层数值核心。
*/

// main.cpp  — 极简AI模型 JingJing  Day1
#include <algorithm>
#include <iostream>
#include <random>
#include <string>
#include <vector>
#include <numeric>

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

/* ---------- 工具函数 ---------- */
void say(const string& msg) { cout << "[JingJing] " << msg << "\n"; }

/* ---------- 核心数据结构 ---------- */
struct Example {
    vector<double> x;  // 特征
    double y;          // 标签
};

/* ---------- 极简模型：均值回归 ---------- */
double predict(const vector<double>& weights,
               const vector<double>& x) {
    return std::inner_product(x.begin(), x.end(),
                              weights.begin(), 0.0);
}

/* ---------- 训练：一次性解析最优权重 ---------- */
void train(const vector<Example>& data, vector<double>& weights) {
    const size_t dim = data.empty() ? 0 : data[0].x.size();
    weights.assign(dim, 0.0);

    vector<double> x_sum(dim, 0.0);
    double y_sum = 0.0;
    for (const auto& e : data) {
        std::transform(e.x.begin(), e.x.end(), x_sum.begin(),
                       x_sum.begin(),
                       [](double xi, double acc) { return acc + xi; });
        y_sum += e.y;
    }

    const double n = static_cast<double>(data.size());
    if (n == 0) return;
    std::transform(x_sum.begin(), x_sum.end(), weights.begin(),
                   [y_sum, n](double acc) { return acc / n; });

    // 计算平均 y
    double y_avg = y_sum / n;

    // 用简单线性缩放让每个权重对平均 y 负责
    std::transform(weights.begin(), weights.end(), weights.begin(),
                   [y_avg](double w) { return w == 0.0 ? 0.0 : y_avg / w; });
}

/* ---------- 交互式演示 ---------- */
int main() {
    /* 构造 4 条简单数据：y = x0 + 2*x1 + 3 */
    vector<Example> dataset = {
        {{1.0, 2.0}, 1.0 + 2.0 * 2.0 + 3.0},
        {{2.0, 3.0}, 2.0 + 2.0 * 3.0 + 3.0},
        {{3.0, 4.0}, 3.0 + 2.0 * 4.0 + 3.0},
        {{4.0, 5.0}, 4.0 + 2.0 * 5.0 + 3.0}};

    vector<double> w;
    train(dataset, w);

    say("训练完成！权重维度：" + std::to_string(w.size()));
    say("权重值：");
    std::for_each(w.begin(), w.end(),
                  [](double wi) { cout << wi << " "; });
    cout << endl;

    /* 随机生成测试样本并预测 */
    std::mt19937 rng(std::random_device{}());
    std::uniform_real_distribution<double> dist(0.0, 10.0);

    for (int i = 0; i < 3; ++i) {
        vector<double> test(2);
        std::generate(test.begin(), test.end(), [&]() { return dist(rng); });
        double y_hat = predict(w, test);
        say("测试样本 (" + std::to_string(test[0]) + ", " +
            std::to_string(test[1]) + ") 预测值 = " + std::to_string(y_hat));
    }

    return 0;
}
